Este relatório, tem como objetivo analisar dados de commits no github. Utilizaremos uma amostra de dados da atividade global do github entre o período de 01/2016 e 05/2017. As linguagens que vamos analisar serão C++ e C# (duas das linguagens mais populares entre os programadores).
Primeiro, será feita a importação dos dados já com as linguagens de interesse filtradas. As variáveis que iremos utilizar serão the_year(o ano referente aos commits), the_month (o mês referente aos commits) e users (quantidade de usuários que fez commits).
dados_github = read_csv(here("data/github-users-committing-filetypes.csv"),
progress = FALSE,
col_types = cols(file_extension = col_character(),
month_day = col_integer(),
the_month = col_integer(),
the_year = col_integer(),
users = col_integer())) %>%
filter(file_extension %in% c("cpp", "cs"))
dados_cs = dados_github %>% filter(file_extension == "cs")
dados_cpp = dados_github %>% filter(file_extension == "cpp")
Antes de responder algumas perguntas, vamos dar uma olhada na linha do tempo das duas linguagens.
Ano de 2016
p =
dados_github %>%
filter(the_year == "2016") %>%
ggplot(aes(x=the_month,
y=users,
text = paste("Mês:",the_month,
"\nQuantidade de Usuários:",
users))) +
labs(y = "Quantidade de usuários", x = "Mês")+
theme(legend.position="none") +
geom_boxplot(fill = "#feffb5") + facet_wrap( ~ file_extension)
ggplotly(p, tooltip = "text")
rm(p)
Ano de 2017
p =
dados_github %>%
filter(the_year == "2017") %>%
ggplot(aes(x=the_month,
y=users,
text = paste("Mês:",the_month,
"\nQuantidade de Usuários:",
users))) +
labs(y = "Quantidade de usuários", x = "Mês")+
theme(legend.position="none") +
geom_boxplot(fill = "#CD86FF") + facet_wrap( ~ file_extension)
ggplotly(p, tooltip = "text")
rm(p)
Como nossas perguntas não são relacionadas à diferenças entre as linguagens, apenas o que nos interessa é a distribuição de cada uma separadamente. Porém, com os boxplots gerados, percebemos que os usuários editam mais arquivos em C++ do que e C#. Além disso, verificamos que há valores discrepantes, por esse motivo, iremos utilizar a mediana nos nossos experimentos.
Há diferença significativa na quantidade de commits da linguagem C# no mês de janeiro de 2016 e 2017?
Assim como na análide do Prob 4 CP 2 iremos aplicar algumas técnicas de estatística. Primeiro, vamos utilizar o método de reamostragem chamado bootstrapping, ele é utilizado para aproximar distribuição na amostra de um levantamento estatístico. Após a aplicação desse método, o Intervalo de Confiança será calculado e assim poderemos inferir o resultado da amostra para toda a população.
amostra_2016 <- dados_cs %>% filter(the_month == "1") %>% filter(the_year == "2016") %>% sample_n(20)
amostra_2016 <- rename(amostra_2016,users_2016 = users)
amostra_2017 <- dados_cs %>% filter(the_month == "1") %>% filter(the_year == "2017") %>% sample_n(20)
amostra_2017 <- rename(amostra_2017,users_2017 = users)
b <- bootstrap(amostra_2016, median(users_2016))
mediana_g1 <- CI.bca(b, probs = c(.05, .95))
mediana_g1
5% 95%
median(users_2016) 867 1164
b <- bootstrap(amostra_2017, median(users_2017))
mediana_g2 <- CI.bca(b, probs = c(.05, .95))
mediana_g2
5% 95%
median(users_2017) 962.5 1213
rm (amostra_2017)
rm(amostra_2016)
rm(b)
Aqui, iremos utilizar uma confiança de 95% para verificar os diferentes intervalos:
df <- data.frame(rbind(mediana_g1,
mediana_g2))
df$medida = row.names(df)
df %>%
ggplot(aes(x = medida, ymin = X5., ymax = X95.)) +
geom_errorbar(width = .2)

rm (df)
Acredito que os intervalos estão grandes porque a quantidade de dados que temos é pequena. Além disso, os intervalos se interceptam e não podemos observar uma diferença significativa. Ou seja, com base nos intervalos de confiança obtidos, não podemos dizer que há uma diferença significativa na quantidade de commits da linguagem C# no mês de janeiro de 2016 e 2017.
E durante os meses de janeiro de 2016 e 2017 há variação na quantidade de commits por dia?
p =
dados_cs %>%
filter(the_year == "2017") %>%
filter(the_month == "1") %>%
ggplot(aes(x=month_day,
y=users,
text = paste("Dia:",month_day,
"\nQuantidade de Usuários:",
users))) +
labs(y = "Quantidade de usuários", x = "Dia")+
theme(legend.position="none") +
geom_bar(stat = 'identity', fill = "#c8d2f4") + facet_wrap( ~ file_extension)
ggplotly(p, tooltip = "text")
rm(p)
Há variação, mas ela acontece entre intervalos de 5 dias, ou seja, esses dias devem ser nos fins de semana, os outros dias mantem a quantidade de commits em uma pequena faixa de intervalo (1114 e 1313 commits).
Há diferença na popularidade da linguagem C++ durante períodos de férias e períodos de aulas?
Para essa pergunta, vamos considerar períodos de férias os mêses de janeiro, junho, julho e dezembro.
amostra_ferias <- dados_cpp %>% filter(the_month %in% c("1", "6", "7", "12")) %>% sample_n(30)
amostra_ferias <- rename(amostra_ferias,users_ferias = users)
amostra_aulas <- dados_cpp %>% filter(the_month %in% c("2", "3", "4", "5", "8", "9", "10", "11")) %>% sample_n(30)
amostra_aulas <- rename(amostra_aulas,users_aulas = users)
b <- bootstrap(amostra_ferias, median(users_ferias))
mediana_g1 <- CI.bca(b, probs = c(.05, .95))
mediana_g1
5% 95%
median(users_ferias) 1539.5 1803.5
b <- bootstrap(amostra_aulas, median(users_aulas))
mediana_g2 <- CI.bca(b, probs = c(.05, .95))
mediana_g2
5% 95%
median(users_aulas) 1445 1834.5
rm(amostra_ferias)
rm(amostra_aulas)
rm(b)
Aqui, iremos utilizar uma confiança de 95% para verificar os diferentes intervalos:
df <- data.frame(rbind(mediana_g1,
mediana_g2))
df$medida = row.names(df)
df %>%
ggplot(aes(x = medida, ymin = X5., ymax = X95.)) +
geom_errorbar(width = .2)

rm (df)
Assim como a resposta da primeira pergunta os intervalos se interceptam e não podemos observar uma diferença significativa. Ou seja, com base nos intervalos de confiança obtidos, não podemos dizer que há uma diferença significativa na quantidade de commits da linguagem C++ entre o período de férias e o período de aulas.
Qual a distribuição dos dados durante o período de férias?
p =
dados_cpp %>%
filter(the_year == "2016") %>%
filter(the_month %in% c("1", "6", "7", "12")) %>%
ggplot(aes(x=month_day,
y=users,
text = paste("Dia:",month_day,
"\nQuantidade de Usuários:",
users))) +
labs(y = "Quantidade de usuários", x = "Dia")+
theme(legend.position="none") +
geom_bar(stat = 'identity', fill = "#afaae7") + facet_wrap( ~ the_month)
ggplotly(p, tooltip = "text")
rm(p)
A quantidade de commits apenas varia nos fins de semana, onde a quantidade é menor, mas nos outros período essa quantidade se mantem em uma pequena faixa.
LS0tCnRpdGxlOiAiRGFkb3MgZGUgY29tbWl0cyBubyBnaXRodWIiCmRhdGU6IDIwMTgtMDctMTQKYXV0aG9yOiAiTWFpbmFyYSBDYXZhbGNhbnRpIGRlIEZhcmlhcyIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKLS0tCgpFc3RlIHJlbGF0w7NyaW8sIHRlbSBjb21vIG9iamV0aXZvIGFuYWxpc2FyIGRhZG9zIGRlIGNvbW1pdHMgbm8gZ2l0aHViLiBVdGlsaXphcmVtb3MgdW1hIGFtb3N0cmEgZGUgZGFkb3MgZGEgYXRpdmlkYWRlIGdsb2JhbCBkbyBnaXRodWIgZW50cmUgbyBwZXLDrW9kbyBkZSAwMS8yMDE2IGUgMDUvMjAxNy4gQXMgbGluZ3VhZ2VucyBxdWUgdmFtb3MgYW5hbGlzYXIgc2Vyw6NvICpDKysqIGUgKkMjKiAoZHVhcyBkYXMgbGluZ3VhZ2VucyBtYWlzIHBvcHVsYXJlcyBlbnRyZSBvcyBwcm9ncmFtYWRvcmVzKS4gCgpgYGB7ciBzZXR1cCwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoaGVyZSkKbGlicmFyeShwbG90bHkpCmxpYnJhcnkocmVzYW1wbGUsIHF1aWV0bHkgPSBUUlVFKQpgYGAKClByaW1laXJvLCBzZXLDoSBmZWl0YSBhIGltcG9ydGHDp8OjbyBkb3MgZGFkb3MgasOhIGNvbSBhcyBsaW5ndWFnZW5zIGRlIGludGVyZXNzZSBmaWx0cmFkYXMuIEFzIHZhcmnDoXZlaXMgcXVlIGlyZW1vcyB1dGlsaXphciBzZXLDo28gKnRoZV95ZWFyKihvIGFubyByZWZlcmVudGUgYW9zIGNvbW1pdHMpLCAqdGhlX21vbnRoKiAobyBtw6pzIHJlZmVyZW50ZSBhb3MgY29tbWl0cykgZSAqdXNlcnMqIChxdWFudGlkYWRlIGRlIHVzdcOhcmlvcyBxdWUgZmV6IGNvbW1pdHMpLgpgYGB7cn0KZGFkb3NfZ2l0aHViID0gcmVhZF9jc3YoaGVyZSgiZGF0YS9naXRodWItdXNlcnMtY29tbWl0dGluZy1maWxldHlwZXMuY3N2IiksCiAgICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9IGNvbHMoZmlsZV9leHRlbnNpb24gPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vbnRoX2RheSA9IGNvbF9pbnRlZ2VyKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZV9tb250aCA9IGNvbF9pbnRlZ2VyKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZV95ZWFyID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlcnMgPSBjb2xfaW50ZWdlcigpKSkgJT4lIAogIGZpbHRlcihmaWxlX2V4dGVuc2lvbiAlaW4lIGMoImNwcCIsICJjcyIpKQoKCmRhZG9zX2NzID0gZGFkb3NfZ2l0aHViICU+JSBmaWx0ZXIoZmlsZV9leHRlbnNpb24gPT0gImNzIikKZGFkb3NfY3BwID0gZGFkb3NfZ2l0aHViICU+JSBmaWx0ZXIoZmlsZV9leHRlbnNpb24gPT0gImNwcCIpCgpgYGAKCkFudGVzIGRlIHJlc3BvbmRlciBhbGd1bWFzIHBlcmd1bnRhcywgdmFtb3MgZGFyIHVtYSBvbGhhZGEgbmEgbGluaGEgZG8gdGVtcG8gZGFzIGR1YXMgbGluZ3VhZ2Vucy4KCiMjIyMgQW5vIGRlIDIwMTYKCmBgYHtyfQpwID0KICBkYWRvc19naXRodWIgJT4lIAogIGZpbHRlcih0aGVfeWVhciA9PSAiMjAxNiIpICU+JSAKICBnZ3Bsb3QoYWVzKHg9dGhlX21vbnRoLCAKICAgICAgICAgICAgIHk9dXNlcnMsCiAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUoIk3DqnM6Iix0aGVfbW9udGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5RdWFudGlkYWRlIGRlIFVzdcOhcmlvczoiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlcnMpKSkgKwogICAgIGxhYnMoeSA9ICJRdWFudGlkYWRlIGRlIHVzdcOhcmlvcyIsIHggPSAiTcOqcyIpKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGdlb21fYm94cGxvdChmaWxsID0gIiNmZWZmYjUiKSArIGZhY2V0X3dyYXAoIH4gZmlsZV9leHRlbnNpb24pCmdncGxvdGx5KHAsIHRvb2x0aXAgPSAidGV4dCIpCgpybShwKQpgYGAKCiMjIyMgQW5vIGRlIDIwMTcKYGBge3J9CnAgPQogIGRhZG9zX2dpdGh1YiAlPiUgCiAgZmlsdGVyKHRoZV95ZWFyID09ICIyMDE3IikgJT4lIAogIGdncGxvdChhZXMoeD10aGVfbW9udGgsIAogICAgICAgICAgICAgeT11c2VycywKICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgiTcOqczoiLHRoZV9tb250aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcblF1YW50aWRhZGUgZGUgVXN1w6FyaW9zOiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VycykpKSArCiAgICAgbGFicyh5ID0gIlF1YW50aWRhZGUgZGUgdXN1w6FyaW9zIiwgeCA9ICJNw6pzIikrCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAiI0NEODZGRiIpICsgZmFjZXRfd3JhcCggfiBmaWxlX2V4dGVuc2lvbikKZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikKCnJtKHApCmBgYAoKQ29tbyBub3NzYXMgcGVyZ3VudGFzIG7Do28gc8OjbyByZWxhY2lvbmFkYXMgw6AgZGlmZXJlbsOnYXMgZW50cmUgYXMgbGluZ3VhZ2VucywgYXBlbmFzIG8gcXVlIG5vcyBpbnRlcmVzc2Egw6kgYSBkaXN0cmlidWnDp8OjbyBkZSBjYWRhIHVtYSBzZXBhcmFkYW1lbnRlLiBQb3LDqW0sIGNvbSBvcyBib3hwbG90cyBnZXJhZG9zLCBwZXJjZWJlbW9zIHF1ZSBvcyB1c3XDoXJpb3MgZWRpdGFtIG1haXMgYXJxdWl2b3MgZW0gKkMrKyogZG8gcXVlIGUgKkMjKi4gQWzDqW0gZGlzc28sIHZlcmlmaWNhbW9zIHF1ZSBow6EgdmFsb3JlcyBkaXNjcmVwYW50ZXMsIHBvciBlc3NlIG1vdGl2bywgaXJlbW9zIHV0aWxpemFyIGEgbWVkaWFuYSBub3Mgbm9zc29zIGV4cGVyaW1lbnRvcy4KCiMjI0jDoSBkaWZlcmVuw6dhIHNpZ25pZmljYXRpdmEgbmEgcXVhbnRpZGFkZSBkZSBjb21taXRzIGRhIGxpbmd1YWdlbSBDIyBubyBtw6pzIGRlIGphbmVpcm8gZGUgMjAxNiBlIDIwMTc/CgpBc3NpbSBjb21vIG5hIGFuw6FsaWRlIGRvICpQcm9iIDQgQ1AgMiogaXJlbW9zIGFwbGljYXIgYWxndW1hcyB0w6ljbmljYXMgZGUgZXN0YXTDrXN0aWNhLiBQcmltZWlybywgdmFtb3MgdXRpbGl6YXIgbyBtw6l0b2RvIGRlIHJlYW1vc3RyYWdlbSBjaGFtYWRvICpib290c3RyYXBwaW5nKiwgZWxlIMOpIHV0aWxpemFkbyBwYXJhIGFwcm94aW1hciBkaXN0cmlidWnDp8OjbyBuYSBhbW9zdHJhIGRlIHVtIGxldmFudGFtZW50byBlc3RhdMOtc3RpY28uIEFww7NzIGEgYXBsaWNhw6fDo28gZGVzc2UgbcOpdG9kbywgbyAqSW50ZXJ2YWxvIGRlIENvbmZpYW7Dp2EqIHNlcsOhIGNhbGN1bGFkbyBlIGFzc2ltIHBvZGVyZW1vcyBpbmZlcmlyIG8gcmVzdWx0YWRvIGRhIGFtb3N0cmEgcGFyYSB0b2RhIGEgcG9wdWxhw6fDo28uCgoKYGBge3J9CmFtb3N0cmFfMjAxNiA8LSBkYWRvc19jcyAlPiUgIGZpbHRlcih0aGVfbW9udGggPT0gIjEiKSAlPiUgZmlsdGVyKHRoZV95ZWFyID09ICIyMDE2IikgJT4lICBzYW1wbGVfbigxMCkKYW1vc3RyYV8yMDE2IDwtIHJlbmFtZShhbW9zdHJhXzIwMTYsdXNlcnNfMjAxNiA9IHVzZXJzKQoKYW1vc3RyYV8yMDE3IDwtIGRhZG9zX2NzICU+JSAgZmlsdGVyKHRoZV9tb250aCA9PSAiMSIpICU+JSBmaWx0ZXIodGhlX3llYXIgPT0gIjIwMTciKSAlPiUgc2FtcGxlX24oMTApCmFtb3N0cmFfMjAxNyA8LSByZW5hbWUoYW1vc3RyYV8yMDE3LHVzZXJzXzIwMTcgPSB1c2VycykKCmIgPC0gYm9vdHN0cmFwKGFtb3N0cmFfMjAxNiwgbWVkaWFuKHVzZXJzXzIwMTYpKQptZWRpYW5hX2cxIDwtIENJLmJjYShiLCBwcm9icyA9IGMoLjA1LCAuOTUpKQptZWRpYW5hX2cxCmIgPC0gYm9vdHN0cmFwKGFtb3N0cmFfMjAxNywgbWVkaWFuKHVzZXJzXzIwMTcpKQptZWRpYW5hX2cyIDwtIENJLmJjYShiLCBwcm9icyA9IGMoLjA1LCAuOTUpKQptZWRpYW5hX2cyCgpybSAoYW1vc3RyYV8yMDE3KQpybShhbW9zdHJhXzIwMTYpCnJtKGIpCmBgYAoKQXF1aSwgaXJlbW9zIHV0aWxpemFyIHVtYSBjb25maWFuw6dhIGRlIDk1JSBwYXJhIHZlcmlmaWNhciBvcyBkaWZlcmVudGVzIGludGVydmFsb3M6CgpgYGB7cn0KZGYgPC0gZGF0YS5mcmFtZShyYmluZChtZWRpYW5hX2cxLCAKICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbmFfZzIpKQpkZiRtZWRpZGEgPSByb3cubmFtZXMoZGYpCmRmICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBtZWRpZGEsIHltaW4gPSBYNS4sIHltYXggPSBYOTUuKSkgKyAKICBnZW9tX2Vycm9yYmFyKHdpZHRoID0gLjIpCnJtIChkZikKYGBgCgpBY3JlZGl0byBxdWUgb3MgaW50ZXJ2YWxvcyBlc3TDo28gZ3JhbmRlcyBwb3JxdWUgYSBxdWFudGlkYWRlIGRlIGRhZG9zIHF1ZSB0ZW1vcyDDqSBwZXF1ZW5hLiBBbMOpbSBkaXNzbywgb3MgaW50ZXJ2YWxvcyBzZSBpbnRlcmNlcHRhbSBlIG7Do28gcG9kZW1vcyBvYnNlcnZhciB1bWEgZGlmZXJlbsOnYSBzaWduaWZpY2F0aXZhLiBPdSBzZWphLCBjb20gYmFzZSBub3MgaW50ZXJ2YWxvcyBkZSBjb25maWFuw6dhIG9idGlkb3MsIG7Do28gcG9kZW1vcyBkaXplciBxdWUgaMOhIHVtYSBkaWZlcmVuw6dhIHNpZ25pZmljYXRpdmEgbmEgcXVhbnRpZGFkZSBkZSBjb21taXRzIGRhIGxpbmd1YWdlbSBDIyBubyBtw6pzIGRlIGphbmVpcm8gZGUgMjAxNiBlIDIwMTcuCgojIyMjRSBkdXJhbnRlIG9zIG1lc2VzIGRlIGphbmVpcm8gZGUgMjAxNiBlIDIwMTcgaMOhIHZhcmlhw6fDo28gbmEgcXVhbnRpZGFkZSBkZSBjb21taXRzIHBvciBkaWE/CgpgYGB7cn0KcCA9CiAgZGFkb3NfY3MgJT4lIAogIGZpbHRlcih0aGVfeWVhciA9PSAiMjAxNyIpICU+JQogIGZpbHRlcih0aGVfbW9udGggPT0gIjEiKSAlPiUgCiAgZ2dwbG90KGFlcyh4PW1vbnRoX2RheSwgCiAgICAgICAgICAgICB5PXVzZXJzLAogICAgICAgICAgICAgdGV4dCA9IHBhc3RlKCJEaWE6Iixtb250aF9kYXksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5RdWFudGlkYWRlIGRlIFVzdcOhcmlvczoiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlcnMpKSkgKwogICAgIGxhYnMoeSA9ICJRdWFudGlkYWRlIGRlIHVzdcOhcmlvcyIsIHggPSAiRGlhIikrCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScsIGZpbGwgPSAiI2M4ZDJmNCIpICsgZmFjZXRfd3JhcCggfiBmaWxlX2V4dGVuc2lvbikKZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikKCnJtKHApCmBgYAoKSMOhIHZhcmlhw6fDo28sIG1hcyBlbGEgYWNvbnRlY2UgZW50cmUgaW50ZXJ2YWxvcyBkZSA1IGRpYXMsIG91IHNlamEsIGVzc2VzIGRpYXMgZGV2ZW0gc2VyIG5vcyBmaW5zIGRlIHNlbWFuYSwgb3Mgb3V0cm9zIGRpYXMgbWFudGVtIGEgcXVhbnRpZGFkZSBkZSBjb21taXRzIGVtIHVtYSBwZXF1ZW5hIGZhaXhhIGRlIGludGVydmFsbyAoMTExNCBlIDEzMTMgY29tbWl0cykuCgojIyNIw6EgZGlmZXJlbsOnYSBuYSBwb3B1bGFyaWRhZGUgZGEgbGluZ3VhZ2VtIEMrKyBkdXJhbnRlIHBlcsOtb2RvcyBkZSBmw6lyaWFzIGUgcGVyw61vZG9zIGRlIGF1bGFzPwoKUGFyYSBlc3NhIHBlcmd1bnRhLCB2YW1vcyBjb25zaWRlcmFyIHBlcsOtb2RvcyBkZSBmw6lyaWFzIG9zIG3DqnNlcyBkZSBqYW5laXJvLCBqdW5obywganVsaG8gZSBkZXplbWJyby4KCmBgYHtyfQphbW9zdHJhX2ZlcmlhcyA8LSBkYWRvc19jcHAgJT4lICBmaWx0ZXIodGhlX21vbnRoICVpbiUgYygiMSIsICI2IiwgIjciLCAiMTIiKSkgJT4lIHNhbXBsZV9uKDMwKQphbW9zdHJhX2ZlcmlhcyA8LSByZW5hbWUoYW1vc3RyYV9mZXJpYXMsdXNlcnNfZmVyaWFzID0gdXNlcnMpCgphbW9zdHJhX2F1bGFzIDwtIGRhZG9zX2NwcCAlPiUgIGZpbHRlcih0aGVfbW9udGggJWluJSBjKCIyIiwgIjMiLCAiNCIsICI1IiwgIjgiLCAiOSIsICIxMCIsICIxMSIpKSAlPiUgc2FtcGxlX24oMzApCmFtb3N0cmFfYXVsYXMgPC0gcmVuYW1lKGFtb3N0cmFfYXVsYXMsdXNlcnNfYXVsYXMgPSB1c2VycykKCmIgPC0gYm9vdHN0cmFwKGFtb3N0cmFfZmVyaWFzLCBtZWRpYW4odXNlcnNfZmVyaWFzKSkKbWVkaWFuYV9nMSA8LSBDSS5iY2EoYiwgcHJvYnMgPSBjKC4wNSwgLjk1KSkKbWVkaWFuYV9nMQpiIDwtIGJvb3RzdHJhcChhbW9zdHJhX2F1bGFzLCBtZWRpYW4odXNlcnNfYXVsYXMpKQptZWRpYW5hX2cyIDwtIENJLmJjYShiLCBwcm9icyA9IGMoLjA1LCAuOTUpKQptZWRpYW5hX2cyCgpybShhbW9zdHJhX2ZlcmlhcykKcm0oYW1vc3RyYV9hdWxhcykKcm0oYikKYGBgCgpBcXVpLCBpcmVtb3MgdXRpbGl6YXIgdW1hIGNvbmZpYW7Dp2EgZGUgOTUlIHBhcmEgdmVyaWZpY2FyIG9zIGRpZmVyZW50ZXMgaW50ZXJ2YWxvczoKCmBgYHtyfQpkZiA8LSBkYXRhLmZyYW1lKHJiaW5kKG1lZGlhbmFfZzEsIAogICAgICAgICAgICAgICAgICAgICAgbWVkaWFuYV9nMikpCmRmJG1lZGlkYSA9IHJvdy5uYW1lcyhkZikKZGYgJT4lIAogIGdncGxvdChhZXMoeCA9IG1lZGlkYSwgeW1pbiA9IFg1LiwgeW1heCA9IFg5NS4pKSArIAogIGdlb21fZXJyb3JiYXIod2lkdGggPSAuMikKcm0gKGRmKQpgYGAKCkFzc2ltIGNvbW8gYSByZXNwb3N0YSBkYSBwcmltZWlyYSBwZXJndW50YSBvcyBpbnRlcnZhbG9zIHNlIGludGVyY2VwdGFtIGUgbsOjbyBwb2RlbW9zIG9ic2VydmFyIHVtYSBkaWZlcmVuw6dhIHNpZ25pZmljYXRpdmEuIE91IHNlamEsIGNvbSBiYXNlIG5vcyBpbnRlcnZhbG9zIGRlIGNvbmZpYW7Dp2Egb2J0aWRvcywgbsOjbyBwb2RlbW9zIGRpemVyIHF1ZSBow6EgdW1hIGRpZmVyZW7Dp2Egc2lnbmlmaWNhdGl2YSBuYSBxdWFudGlkYWRlIGRlIGNvbW1pdHMgZGEgbGluZ3VhZ2VtIEMrKyBlbnRyZSBvIHBlcsOtb2RvIGRlIGbDqXJpYXMgZSBvIHBlcsOtb2RvIGRlIGF1bGFzLgoKIyMjI1F1YWwgYSBkaXN0cmlidWnDp8OjbyBkb3MgZGFkb3MgZHVyYW50ZSBvIHBlcsOtb2RvIGRlIGbDqXJpYXM/CgpgYGB7cn0KcCA9CiAgZGFkb3NfY3BwICU+JSAKICBmaWx0ZXIodGhlX3llYXIgPT0gIjIwMTYiKSAlPiUKICBmaWx0ZXIodGhlX21vbnRoICVpbiUgYygiMSIsICI2IiwgIjciLCAiMTIiKSkgJT4lIAogIGdncGxvdChhZXMoeD1tb250aF9kYXksIAogICAgICAgICAgICAgeT11c2VycywKICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgiRGlhOiIsbW9udGhfZGF5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxuUXVhbnRpZGFkZSBkZSBVc3XDoXJpb3M6IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJzKSkpICsKICAgICBsYWJzKHkgPSAiUXVhbnRpZGFkZSBkZSB1c3XDoXJpb3MiLCB4ID0gIkRpYSIpKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknLCBmaWxsID0gIiNhZmFhZTciKSArIGZhY2V0X3dyYXAoIH4gdGhlX21vbnRoKQpnZ3Bsb3RseShwLCB0b29sdGlwID0gInRleHQiKQoKcm0ocCkKYGBgCgpBIHF1YW50aWRhZGUgZGUgY29tbWl0cyBhcGVuYXMgdmFyaWEgbm9zIGZpbnMgZGUgc2VtYW5hLCBvbmRlIGEgcXVhbnRpZGFkZSDDqSBtZW5vciwgbWFzIG5vcyBvdXRyb3MgcGVyw61vZG8gZXNzYSBxdWFudGlkYWRlIHNlIG1hbnRlbSBlbSB1bWEgcGVxdWVuYSBmYWl4YS4=